package tool

import (
	"MoSkeleton/config/consts"
	"MoSkeleton/framework"
	consts2 "MoSkeleton/framework/core/consts"
	"MoSkeleton/framework/core/dto/request"
	"MoSkeleton/framework/core/dto/response"
	"MoSkeleton/framework/core/moerrors"
	"MoSkeleton/framework/utils"
	tool2 "MoSkeleton/models/tool"
	"MoSkeleton/services/base"
	tool3 "MoSkeleton/web/pogos/request/tool"
	"MoSkeleton/web/pogos/response/tool"
	"errors"
	"gorm.io/gorm"
	"os"
	"path/filepath"
)

type GenTemplateClassifyService struct {
	base.BaseService
}

func (g *GenTemplateClassifyService) GetAllClassifys() ([]*tool.GenTemplateClassifySimpleItemResp, error) {
	var classifys = make([]*tool.GenTemplateClassifySimpleItemResp, 0)
	err := g.GetDb(nil).Model(&tool2.GenTemplateClassify{}).Where("status=?", consts.U_NORMAL).Order("list_order asc").Find(&classifys).Error
	return classifys, err
}

func (g *GenTemplateClassifyService) GetClassifyPage(pageReq *tool3.GenTemplateClassifyPageReq) (*response.PageResult, error) {
	db := g.getClassifyVo(g.GetDb(nil), pageReq)
	var total int64
	result := make([]*tool.GenTemplateClassifyItemResp, 0)
	if err := db.Count(&total).Offset(pageReq.Offset()).Limit(pageReq.Limit()).Find(&result).Error; err != nil {
		return nil, err
	}
	pageResult := response.NewFromPageInfoAndData(&pageReq.PageInfo, &result, total)
	return pageResult, nil
}

func (g *GenTemplateClassifyService) GetClassifyById(id uint64) (*tool.GenTemplateClassifyDetailResp, error) {
	detailResp := &tool.GenTemplateClassifyDetailResp{}
	if id > 0 {
		item := tool.GenTemplateClassifyItemResp{}
		if err := g.GetDb(nil).Model(&tool2.GenTemplateClassify{}).Where("id=?", id).First(&item).Error; err != nil {
			return nil, err
		}
		detailResp.Classify = &item
		templateFileNames, err := genTemplateFileService.GetTemplateFilesByClassifyId(item.ID)
		if err != nil {
			return nil, err
		}
		detailResp.TemplateFileNames = &templateFileNames
	}
	return detailResp, nil
}
func (g *GenTemplateClassifyService) GetClassifyByBizId(bizId uint64) (*tool.GenTemplateClassifyItemResp, error) {
	item := tool.GenTemplateClassifyItemResp{}
	db := g.GetDb(nil).Select("gtc.*, gb.is_ignore_table_prefix").Table("gen_template_classify gtc")
	db = db.Joins("left join gen_biz gb on gb.classify_id=gtc.id")
	if err := db.Where("gb.id=?", bizId).First(&item).Error; err != nil {
		return nil, err
	}
	return &item, nil
}

func (g *GenTemplateClassifyService) AddClassify(addReq *tool3.GenTemplateClassifyAddReq) (bool, error) {
	if addReq.IsDetectTemplate == consts.U_NO {
		//清空slice
		addReq.TemplateFileNames = addReq.TemplateFileNames[:0]
	}
	classify := new(tool2.GenTemplateClassify)
	if err := utils.CopyStruct(classify, addReq); err != nil {
		return false, err
	}
	err := g.GetDb(nil).Transaction(func(tx *gorm.DB) error {
		result := tx.Model(classify).Create(classify)
		if result.Error != nil {
			return result.Error
		}
		if addReq.IsDetectTemplate == consts.U_YES {
			if err := genTemplateFileService.AddTemplateFiles(tx, addReq.TemplateFileNames, classify.ID, addReq.CreatedBy); err != nil {
				return err
			}
		}
		if addReq.IsDefault == consts.U_YES {
			if err := g.updateUndefaultExcept(tx, classify.ID); err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return false, err
	}
	return true, nil
}

func (g *GenTemplateClassifyService) UpdateClassify(updateReq *tool3.GenTemplateClassifyUpdateReq) error {
	if updateReq.IsDetectTemplate == consts.U_NO {
		//清空slice
		updateReq.TemplateFileNames = updateReq.TemplateFileNames[:0]
	}
	classify := new(tool2.GenTemplateClassify)
	if err := utils.CopyStruct(classify, updateReq); err != nil {
		return err
	}
	if err := g.GetDb(nil).Transaction(func(tx *gorm.DB) error {
		if exists, err := g.checkDefaultExcept(tx, classify.ID); err != nil {
			return err
		} else {
			if !exists && (classify.IsDefault != consts.U_YES || classify.Status == consts.U_DISABLE) {
				return moerrors.NewWithMsg("必须有一个默认分类")
			} else if exists && classify.IsDefault == consts.U_YES {
				if err := g.updateUndefaultExcept(tx, classify.ID); err != nil {
					return err
				}
			}
		}
		if err := g.GetDb(tx).Updates(classify).Error; err != nil {
			return err
		}
		if err := genTemplateFileService.RemoveTemplateFilesByClassifyIds(tx, &[]uint64{classify.ID}); err != nil {
			return err
		}
		if updateReq.IsDetectTemplate == consts.U_YES {
			if err := genTemplateFileService.AddTemplateFiles(tx, updateReq.TemplateFileNames, classify.ID, updateReq.UpdatedBy); err != nil {
				return err
			}
		}
		return nil
	}); err != nil {
		return err
	}
	return nil
}

func (g *GenTemplateClassifyService) DeleteClassify(ids *[]uint64) error {
	if len(*ids) <= 0 {
		framework.MoLogger.Info("delete classify id is null")
		return nil
	}
	return g.GetDb(nil).Transaction(func(tx *gorm.DB) error {
		if err := genTemplateFileService.RemoveTemplateFilesByClassifyIds(tx, ids); err != nil {
			return err
		}
		return tx.Delete(&tool2.GenTemplateClassify{}, "id in (?)", *ids).Error
	})
}

func (g *GenTemplateClassifyService) DetectTemplateFiles(classifyCode string) ([]string, error) {
	if classifyCode == "" {
		return nil, moerrors.NewValidateError(consts2.ValidatorParamsCheckFailCode, "分类编码无效")
	}
	classifyPath := filepath.Join(framework.WorkDir, consts2.CodeGenPath, classifyCode)
	if _, err := os.Stat(classifyPath); err != nil {
		return nil, moerrors.NewValidateMsgError(consts2.ValidatorParamsCheckFailCode, "分类目录不存在", err)
	}
	// 查找claassifyPath目录下，以.tpl 为后缀的文件列表
	return utils.GetFileListBySuffix(classifyPath, ".tpl", false)
}

func (g *GenTemplateClassifyService) ChangeStatus(changeStatusReq *request.ChangeStatusReq) error {
	classify := new(tool2.GenTemplateClassify)
	classify.ID = changeStatusReq.ID
	classify.Status = changeStatusReq.Status

	if classify.Status == consts.U_DISABLE {
		old := &tool2.GenTemplateClassify{}
		if err := g.GetDb(nil).Model(old).Where("id=?", changeStatusReq.ID).First(&old).Error; err != nil {
			return err
		}
		if old.IsDefault == consts.U_YES {
			return moerrors.NewValidateError(consts2.ValidatorParamsCheckFailCode, "必须有一个默认分类")
		}
	}
	return classify.ChangeStatus(nil, classify)
}
func (g *GenTemplateClassifyService) getClassifyVo(tx *gorm.DB, pageReq *tool3.GenTemplateClassifyPageReq) *gorm.DB {
	db := tx.Table("gen_template_classify gc").Select("gc.* , (select count(1) from gen_template_files tf where tf.classify_id=gc.id) as file_count")
	if pageReq.Status != "" {
		db.Where("gc.status = ?", pageReq.Status)
	}
	if pageReq.Title != "" {
		db.Where("gc.title like ?", "%"+pageReq.Title+"%")
	}
	if pageReq.ClassifyCode != "" {
		db.Where("gc.classify_code like ?", "%"+pageReq.ClassifyCode+"%")
	}
	beginTime, ok := pageReq.GetParamValue("beginTime")
	if ok && beginTime != "" {
		if beginTime = pageReq.FormatBeginTime(beginTime); beginTime != "" {
			db.Where("gc.created_at >= ?", beginTime)
		}
	}
	endTime, ok := pageReq.GetParamValue("endTime")
	if ok && endTime != "" {
		if endTime = pageReq.FormatEndTime(endTime); endTime != "" {
			db.Where("gc.created_at <= ?", endTime)
		}
	}
	return db
}

// 检测除了classsifyId， 是否有默认分类
func (g *GenTemplateClassifyService) checkDefaultExcept(tx *gorm.DB, classsifyId uint64) (bool, error) {
	classify := new(tool2.GenTemplateClassify)
	result := g.GetDb(tx).Where("id != ? and is_default=?", classsifyId, consts.U_YES).First(classify)
	if result.Error != nil && errors.Is(result.Error, gorm.ErrRecordNotFound) {
		return false, nil
	}
	return result.RowsAffected > 0, result.Error
}

func (g *GenTemplateClassifyService) updateUndefaultExcept(tx *gorm.DB, classsifyId uint64) error {
	return g.GetDb(tx).Model(&tool2.GenTemplateClassify{}).Where("id != ? and is_default=?", classsifyId, consts.U_YES).Update("is_default", consts.U_NO).Error
}
